﻿namespace WCBG.ToolsForUnity.Tools
{
    using System;
    using UnityEngine;

    public class FTween
    {
        private float clerp(float start, float end, float value)
        {
            float num = 0f;
            float num2 = 360f;
            float num3 = Mathf.Abs((num2 - num) * 0.5f);
            float num5 = 0f;
            if ((end - start) < -num3)
            {
                num5 = ((num2 - start) + end) * value;
                return (start + num5);
            }
            if ((end - start) > num3)
            {
                num5 = -((num2 - end) + start) * value;
                return (start + num5);
            }
            return (start + ((end - start) * value));
        }

        private float easeInBack(float start, float end, float value)
        {
            end -= start;
            value /= 1f;
            float num = 1.70158f;
            return ((((end * value) * value) * (((num + 1f) * value) - num)) + start);
        }

        private float easeInBounce(float start, float end, float value)
        {
            end -= start;
            float num = 1f;
            return ((end - this.easeOutBounce(0f, end, num - value)) + start);
        }

        private float easeInCirc(float start, float end, float value)
        {
            end -= start;
            return ((-end * (Mathf.Sqrt(1f - (value * value)) - 1f)) + start);
        }

        private float easeInCubic(float start, float end, float value)
        {
            end -= start;
            return ((((end * value) * value) * value) + start);
        }

        private float easeInElastic(float start, float end, float value)
        {
            end -= start;
            float num = 1f;
            float num2 = num * 0.3f;
            float num3 = 0f;
            float num4 = 0f;
            if (value == 0f)
            {
                return start;
            }
            if ((value /= num) == 1f)
            {
                return (start + end);
            }
            if ((num4 == 0f) || (num4 < Mathf.Abs(end)))
            {
                num4 = end;
                num3 = num2 / 4f;
            }
            else
            {
                num3 = (num2 / 6.283185f) * Mathf.Asin(end / num4);
            }
            return (-((num4 * Mathf.Pow(2f, 10f * --value)) * Mathf.Sin((((value * num) - num3) * 6.283185f) / num2)) + start);
        }

        private float easeInExpo(float start, float end, float value)
        {
            end -= start;
            return ((end * Mathf.Pow(2f, 10f * (value - 1f))) + start);
        }

        private float easeInOutBack(float start, float end, float value)
        {
            float num = 1.70158f;
            end -= start;
            value /= 0.5f;
            if (value < 1f)
            {
                num *= 1.525f;
                return (((end * 0.5f) * ((value * value) * (((num + 1f) * value) - num))) + start);
            }
            value -= 2f;
            num *= 1.525f;
            return (((end * 0.5f) * (((value * value) * (((num + 1f) * value) + num)) + 2f)) + start);
        }

        private float easeInOutBounce(float start, float end, float value)
        {
            end -= start;
            float num = 1f;
            if (value < (num * 0.5f))
            {
                return ((this.easeInBounce(0f, end, value * 2f) * 0.5f) + start);
            }
            return (((this.easeOutBounce(0f, end, (value * 2f) - num) * 0.5f) + (end * 0.5f)) + start);
        }

        private float easeInOutCirc(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return (((-end * 0.5f) * (Mathf.Sqrt(1f - (value * value)) - 1f)) + start);
            }
            value -= 2f;
            return (((end * 0.5f) * (Mathf.Sqrt(1f - (value * value)) + 1f)) + start);
        }

        private float easeInOutCubic(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return (((((end * 0.5f) * value) * value) * value) + start);
            }
            value -= 2f;
            return (((end * 0.5f) * (((value * value) * value) + 2f)) + start);
        }

        private float easeInOutElastic(float start, float end, float value)
        {
            end -= start;
            float num = 1f;
            float num2 = num * 0.3f;
            float num3 = 0f;
            float num4 = 0f;
            if (value == 0f)
            {
                return start;
            }
            if ((value /= (num * 0.5f)) == 2f)
            {
                return (start + end);
            }
            if ((num4 == 0f) || (num4 < Mathf.Abs(end)))
            {
                num4 = end;
                num3 = num2 / 4f;
            }
            else
            {
                num3 = (num2 / 6.283185f) * Mathf.Asin(end / num4);
            }
            if (value < 1f)
            {
                return ((-0.5f * ((num4 * Mathf.Pow(2f, 10f * --value)) * Mathf.Sin((((value * num) - num3) * 6.283185f) / num2))) + start);
            }
            return (((((num4 * Mathf.Pow(2f, -10f * --value)) * Mathf.Sin((((value * num) - num3) * 6.283185f) / num2)) * 0.5f) + end) + start);
        }

        private float easeInOutExpo(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return (((end * 0.5f) * Mathf.Pow(2f, 10f * (value - 1f))) + start);
            }
            value--;
            return (((end * 0.5f) * (-Mathf.Pow(2f, -10f * value) + 2f)) + start);
        }

        private float easeInOutQuad(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return ((((end * 0.5f) * value) * value) + start);
            }
            value--;
            return (((-end * 0.5f) * ((value * (value - 2f)) - 1f)) + start);
        }

        private float easeInOutQuart(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return ((((((end * 0.5f) * value) * value) * value) * value) + start);
            }
            value -= 2f;
            return (((-end * 0.5f) * ((((value * value) * value) * value) - 2f)) + start);
        }

        private float easeInOutQuint(float start, float end, float value)
        {
            value /= 0.5f;
            end -= start;
            if (value < 1f)
            {
                return (((((((end * 0.5f) * value) * value) * value) * value) * value) + start);
            }
            value -= 2f;
            return (((end * 0.5f) * (((((value * value) * value) * value) * value) + 2f)) + start);
        }

        private float easeInOutSine(float start, float end, float value)
        {
            end -= start;
            return (((-end * 0.5f) * (Mathf.Cos(3.141593f * value) - 1f)) + start);
        }

        private float easeInQuad(float start, float end, float value)
        {
            end -= start;
            return (((end * value) * value) + start);
        }

        private float easeInQuart(float start, float end, float value)
        {
            end -= start;
            return (((((end * value) * value) * value) * value) + start);
        }

        private float easeInQuint(float start, float end, float value)
        {
            end -= start;
            return ((((((end * value) * value) * value) * value) * value) + start);
        }

        private float easeInSine(float start, float end, float value)
        {
            end -= start;
            return (((-end * Mathf.Cos(value * 1.570796f)) + end) + start);
        }

        private float easeOutBack(float start, float end, float value)
        {
            float num = 1.70158f;
            end -= start;
            value--;
            return ((end * (((value * value) * (((num + 1f) * value) + num)) + 1f)) + start);
        }

        private float easeOutBounce(float start, float end, float value)
        {
            value /= 1f;
            end -= start;
            if (value < 0.3636364f)
            {
                return ((end * ((7.5625f * value) * value)) + start);
            }
            if (value < 0.7272727f)
            {
                value -= 0.5454546f;
                return ((end * (((7.5625f * value) * value) + 0.75f)) + start);
            }
            if (value < 0.90909090909090906)
            {
                value -= 0.8181818f;
                return ((end * (((7.5625f * value) * value) + 0.9375f)) + start);
            }
            value -= 0.9545454f;
            return ((end * (((7.5625f * value) * value) + 0.984375f)) + start);
        }

        private float easeOutCirc(float start, float end, float value)
        {
            value--;
            end -= start;
            return ((end * Mathf.Sqrt(1f - (value * value))) + start);
        }

        private float easeOutCubic(float start, float end, float value)
        {
            value--;
            end -= start;
            return ((end * (((value * value) * value) + 1f)) + start);
        }

        private float easeOutElastic(float start, float end, float value)
        {
            end -= start;
            float num = 1f;
            float num2 = num * 0.3f;
            float num3 = 0f;
            float num4 = 0f;
            if (value == 0f)
            {
                return start;
            }
            if ((value /= num) == 1f)
            {
                return (start + end);
            }
            if ((num4 == 0f) || (num4 < Mathf.Abs(end)))
            {
                num4 = end;
                num3 = num2 * 0.25f;
            }
            else
            {
                num3 = (num2 / 6.283185f) * Mathf.Asin(end / num4);
            }
            return ((((num4 * Mathf.Pow(2f, -10f * value)) * Mathf.Sin((((value * num) - num3) * 6.283185f) / num2)) + end) + start);
        }

        private float easeOutExpo(float start, float end, float value)
        {
            end -= start;
            return ((end * (-Mathf.Pow(2f, -10f * value) + 1f)) + start);
        }

        private float easeOutQuad(float start, float end, float value)
        {
            end -= start;
            return (((-end * value) * (value - 2f)) + start);
        }

        private float easeOutQuart(float start, float end, float value)
        {
            value--;
            end -= start;
            return ((-end * ((((value * value) * value) * value) - 1f)) + start);
        }

        private float easeOutQuint(float start, float end, float value)
        {
            value--;
            end -= start;
            return ((end * (((((value * value) * value) * value) * value) + 1f)) + start);
        }

        private float easeOutSine(float start, float end, float value)
        {
            end -= start;
            return ((end * Mathf.Sin(value * 1.570796f)) + start);
        }

        private float linear(float start, float end, float value) => 
            Mathf.Lerp(start, end, value);

        private float punch(float amplitude, float value)
        {
            float num = 9f;
            if (value == 0f)
            {
                return 0f;
            }
            if (value == 1f)
            {
                return 0f;
            }
            float num2 = 0.3f;
            num = (num2 / 6.283185f) * Mathf.Asin(0f);
            return ((amplitude * Mathf.Pow(2f, -10f * value)) * Mathf.Sin((((value * 1f) - num) * 6.283185f) / num2));
        }

        private float spring(float start, float end, float value)
        {
            value = Mathf.Clamp01(value);
            value = ((Mathf.Sin((value * 3.141593f) * (0.2f + (((2.5f * value) * value) * value))) * Mathf.Pow(1f - value, 2.2f)) + value) * (1f + (1.2f * (1f - value)));
            return (start + ((end - start) * value));
        }

        public enum EaseType
        {
            easeInQuad,
            easeOutQuad,
            easeInOutQuad,
            easeInCubic,
            easeOutCubic,
            easeInOutCubic,
            easeInQuart,
            easeOutQuart,
            easeInOutQuart,
            easeInQuint,
            easeOutQuint,
            easeInOutQuint,
            easeInSine,
            easeOutSine,
            easeInOutSine,
            easeInExpo,
            easeOutExpo,
            easeInOutExpo,
            easeInCirc,
            easeOutCirc,
            easeInOutCirc,
            linear,
            spring,
            easeInBounce,
            easeOutBounce,
            easeInOutBounce,
            easeInBack,
            easeOutBack,
            easeInOutBack,
            easeInElastic,
            easeOutElastic,
            easeInOutElastic,
            punch
        }
    }
}

